package com.webchat.ugc.service.mall;


import com.webchat.common.bean.APIPageResponseBean;
import com.webchat.common.constants.WebConstant;
import com.webchat.common.enums.RedisKeyEnum;
import com.webchat.common.enums.mall.MallOrderLogisticsStatusEnum;
import com.webchat.common.enums.mall.MallOrderPaymentStatusEnum;
import com.webchat.common.enums.messagequeue.MessageQueueEnum;
import com.webchat.common.enums.payment.PaymentBusinessActionEnum;
import com.webchat.common.enums.payment.PaymentOrderStatusEnum;
import com.webchat.common.enums.payment.PaymentTransEventEnum;
import com.webchat.common.enums.payment.PaymentTransTypeEnum;
import com.webchat.common.exception.BusinessException;
import com.webchat.common.service.RedisService;
import com.webchat.common.service.SnowflakeIdGeneratorService;
import com.webchat.common.service.messagequeue.producer.MessageQueueProducer;
import com.webchat.common.util.JsonUtil;
import com.webchat.domain.dto.payment.CallBackRequestBodyDTO;
import com.webchat.domain.dto.payment.PaymentOrderCreateDTO;
import com.webchat.domain.dto.payment.PaymentResultDTO;
import com.webchat.domain.dto.queue.MallOrderTimeoutMessageDTO;
import com.webchat.domain.enums.payment.PaymentResultCodeEnum;
import com.webchat.domain.vo.request.mall.CreateProductPaymentOrderReqVO;
import com.webchat.domain.vo.request.mall.PreCreateProductOrderReqVO;
import com.webchat.domain.vo.response.mall.MallProductOrderResponseVO;
import com.webchat.domain.vo.response.mall.MallSKUResponseVO;
import com.webchat.domain.vo.response.mall.MallSPUBaseVO;
import com.webchat.domain.vo.response.mall.MallSPUDetailVO;
import com.webchat.domain.vo.response.mall.MallShopBaseVO;
import com.webchat.domain.vo.response.mall.MallUserProductOrderResponseVO;
import com.webchat.ugc.repository.dao.mall.IMallProductOrderDAO;
import com.webchat.ugc.repository.entity.mall.MallProductOrderEntity;
import com.webchat.ugc.service.PaymentService;
import com.webchat.ugc.service.callback.payment.AbstractPaymentCallback;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.C;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Service
public class MallProductOrderService extends AbstractPaymentCallback {


    @Autowired
    private IMallProductOrderDAO productOrderDAO;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private MallProductService productService;
    @Autowired
    private MallProductStockService mallProductStockService;
    @Autowired
    private SnowflakeIdGeneratorService snowflakeIdGeneratorService;
    @Autowired
    private MessageQueueProducer<MallOrderTimeoutMessageDTO, Long> messageQueueProducer;

    /**
     * 订单等待支付超时策略：订单预创建成功10min内必须完成支付
     *
     */
    private static final Long ORDER_WAIT_PAYMENT_TIMEOUT = 2 * 60 * 1000L;

    /**
     * 预创建订单
     *
     * @return
     */
    public String preCreateOrder(PreCreateProductOrderReqVO preCreateProductOrderReq) {

        Integer productCount = preCreateProductOrderReq.getProductCount();

        // 1. 获取并校验SKU信息
        // RPC 请求商品服务（PGC）
        Long productId = preCreateProductOrderReq.getSpuId();
        // 底层实现基于 LocalCache + Redis 两级缓存实现，这里性能OK的
        MallSPUDetailVO product = productService.productInfo(productId);
        // 创建订单业务数据校验
        MallSKUResponseVO sku = doCheckPreCreateOrderReq(preCreateProductOrderReq, product);

        // 2. 库存预扣减
        boolean preReduceStockRes = mallProductStockService.reduceStock(product.getId(), sku.getId(), productCount);
        Assert.isTrue(preReduceStockRes, "下单失败：库存服务异常");

        // 4. 缓存订单信息
        // 基于雪花算法 + redis自增尾数 保证分布式下全局唯一
        String orderNo = snowflakeIdGeneratorService.generateId();
        // 5. 持久化订单数据
        long timeoutTime = System.currentTimeMillis() + ORDER_WAIT_PAYMENT_TIMEOUT;
        MallProductOrderEntity orderEntity = null;
        try {
            orderEntity = doPreCreateOrder(orderNo, preCreateProductOrderReq, sku, timeoutTime);
        } catch (Exception orderOrmException) {
            // 订单持久化异常
            // 回滚库存
            boolean rollBackRes = mallProductStockService.rollback(productId, sku.getId(), productCount);
            if (!rollBackRes) {
                // TODO
                // 重试方案参考：com.webchat.pay.service.PaymentCallBackService.callBack
            }
            throw new BusinessException("下单异常");
        }
        // 6. 订单数据缓存
        try {
            doCacheOrderCacheByPreCreateOrder(orderEntity);
        } catch (Exception orderCacheException) {
            // 订单缓存异常
            // 处理策略：本地订单预创建希望成功的，不阻塞我们订单创建流程
            doDelOrderCacheByPreCreateOrder(orderEntity);
        }
        // 7. 订单丢入延迟队列，实现超过支付截止时间我们需要释放库存（解决茅坑不拉屎）
        MallOrderTimeoutMessageDTO orderTimeoutMessage = new MallOrderTimeoutMessageDTO();
        // 当前订单待支付超时时间：10min后
        orderTimeoutMessage.setTime(timeoutTime);
        orderTimeoutMessage.setSpuId(productId);
        orderTimeoutMessage.setOrderNo(orderNo);
        messageQueueProducer.prioritySend(MessageQueueEnum.QUEUE_MALL_ORDER_TIMEOUT_DELAY_MESSAGE, orderTimeoutMessage, timeoutTime);
        return orderNo;
    }


    private void doCacheOrderCacheByPreCreateOrder(MallProductOrderEntity orderEntity) {
        // 订单详情数据缓存
        doCacheProductOrder(orderEntity.getOrderNo(), orderEntity);
        // 添加到用户全部订单列表缓存
        String orderNo = orderEntity.getOrderNo();
        String userId = orderEntity.getUserId();
        doCacheUserOrderList(orderNo,
                            userId,
                            WebConstant.CACHE_NONE_NUMBER,
                            WebConstant.CACHE_NONE_NUMBER,
                            orderEntity.getCreateDate().getTime());
        // 添加到用户全部订单列表缓存
        doCacheUserOrderList(orderNo,
                            userId,
                            MallOrderPaymentStatusEnum.WAIT.getStatus(),
                            MallOrderLogisticsStatusEnum.NONE.getStatus(),
                            orderEntity.getCreateDate().getTime());
    }

    private void doDelOrderCacheByPreCreateOrder(MallProductOrderEntity orderEntity) {
        String orderNo = orderEntity.getOrderNo();
        String userId = orderEntity.getUserId();
        // 订单详情数据缓存
        doDelProductOrderCache(orderNo);
        // 添加到用户全部订单列表缓存
        doDelUserOrderListCache(orderNo,
                                userId,
                                WebConstant.CACHE_NONE_NUMBER,
                                WebConstant.CACHE_NONE_NUMBER);
        // 添加到用户全部订单列表缓存
        doDelUserOrderListCache(orderNo,
                                userId,
                                MallOrderPaymentStatusEnum.WAIT.getStatus(),
                                MallOrderLogisticsStatusEnum.NONE.getStatus());
    }

    /**
     * 真正订单创建
     *
     * @param orderNo
     * @param preCreateProductOrderReqVO
     */
    private MallProductOrderEntity doPreCreateOrder(String orderNo,
                                                    PreCreateProductOrderReqVO preCreateProductOrderReqVO,
                                                    MallSKUResponseVO sku,
                                                    long timeoutTime) {
        MallProductOrderEntity mallProductOrderEntity = convertOrderEntity(orderNo, preCreateProductOrderReqVO, sku, timeoutTime);
        return productOrderDAO.save(mallProductOrderEntity);
    }

    /**
     * 基于订单编号，刷新订单缓存
     *
     * @param orderNo
     */
    private MallProductOrderResponseVO doCacheProductOrder(String orderNo) {
        MallProductOrderEntity order = productOrderDAO.findAllByOrderNo(orderNo);
        return this.doCacheProductOrder(orderNo, order);
    }

    /**
     * 订单详情缓存
     *
     * @param mallProductOrderEntity
     */
    private MallProductOrderResponseVO doCacheProductOrder(String orderNo,
                                                           MallProductOrderEntity mallProductOrderEntity) {
        String cacheKey = orderCacheKey(orderNo);
        if (mallProductOrderEntity == null) {
            redisService.set(cacheKey, WebConstant.CACHE_NONE,
                    RedisKeyEnum.MALL_PRODUCT_ORDER_DETAIL_CACHE.getExpireTime());
            return null;
        }
        MallProductOrderResponseVO productOrder = convertVOByOrderEntity(mallProductOrderEntity);
        redisService.set(cacheKey, JsonUtil.toJsonString(productOrder),
                         RedisKeyEnum.MALL_PRODUCT_ORDER_DETAIL_CACHE.getExpireTime());
        return productOrder;
    }

    /**
     * 订单（编号/索引）加入用户列表缓存
     *
     * @param orderNo
     * @param userId
     * @param paymentStatus
     * @param logisticsStatus
     * @param score
     */
    private void doCacheUserOrderList(String orderNo, String userId,
                                      Integer paymentStatus, Integer logisticsStatus,
                                      Long score) {
        String userOrderListCacheKey = userOrderListCacheKey(userId, paymentStatus, logisticsStatus);
        redisService.zadd(userOrderListCacheKey, orderNo, score,
                          RedisKeyEnum.MALL_USER_PRODUCT_ORDER_LIST_CACHE.getExpireTime());
    }

    /**
     * 删除用户列表旧的订单数据
     *
     * @param orderNo
     * @param userId
     * @param paymentStatus
     * @param logisticsStatus
     */
    private void doDelUserOrderListCache(String orderNo, String userId, Integer paymentStatus, Integer logisticsStatus) {

        String delUserOrderListCacheKey = userOrderListCacheKey(userId, paymentStatus, logisticsStatus);
        redisService.zremove(delUserOrderListCacheKey, orderNo);
    }

    public APIPageResponseBean<Object> getUserOrderList(String userId,
                                                        Integer paymentStatus,
                                                        Integer logisticsStatus,
                                                        int pageNo, int pageSize) {
//        String userOrderListCacheKey = userOrderListCacheKey(userId, paymentStatus, logisticsStatus);
//        int start = (pageNo - 1) * pageSize;
//        int end = start + pageSize;
//        Set<String> orderNoSet = redisService.zreverseRange(userOrderListCacheKey, start, end);
//
        return null;
    }

    /**
     * 删除订单详情缓存
     *
     * @param orderNo
     */
    private void doDelProductOrderCache(String orderNo) {

        String cacheKey = this.orderCacheKey(orderNo);
        redisService.remove(cacheKey);
    }

    /**
     * 订单详情缓存（String）
     *
     * @param orderNo
     * @return
     */
    private String orderCacheKey(String orderNo) {

        return RedisKeyEnum.MALL_PRODUCT_ORDER_DETAIL_CACHE.formatKey(orderNo);
    }

    /**
     * 用户订单列表缓存（Zset）
     *
     * @param userId            用户id
     * @param paymentStatus     支付状态
     * @param logisticsStatus   物流发货状态
     * @return
     */
    private String userOrderListCacheKey(String userId, Integer paymentStatus, Integer logisticsStatus) {

        return RedisKeyEnum.MALL_USER_PRODUCT_ORDER_LIST_CACHE.formatKey(userId, paymentStatus, logisticsStatus);
    }

    /**
     * 校验与创建订单信息
     *
     * @param preCreateProductOrderReq
     * @param product
     */
    private MallSKUResponseVO doCheckPreCreateOrderReq(PreCreateProductOrderReqVO preCreateProductOrderReq,
                                          MallSPUDetailVO product) {

        Assert.notNull(product, "订单创建异常：商品不存在");
        Long skuId = preCreateProductOrderReq.getSkuId();
        List<MallSKUResponseVO> skuInfos = product.getSkuList().stream().filter(
                        sku -> ObjectUtils.equals(sku.getId(), skuId)).toList();
        Assert.isTrue(CollectionUtils.isNotEmpty(skuInfos), "订单创建异常：销售属性不存在");
        // 其他数据校验 ... TODO

        return skuInfos.get(0);
    }

    /**
     * 创建支付订单
     *
     * @return
     */
    public String createPaymentOrder(CreateProductPaymentOrderReqVO createProductPaymentOrderReq) {

        String orderNo = createProductPaymentOrderReq.getOrderNo();
        String userId = createProductPaymentOrderReq.getUserId();
        // 走redis获取商品订单详情
        MallUserProductOrderResponseVO productOrder = getUserOrder(userId, orderNo);
        Assert.notNull(productOrder, "商品订单不存在");
        Integer currPaymentStatus = productOrder.getOrder().getPaymentStatus();
        Assert.isTrue(PaymentOrderStatusEnum.allowPayment(currPaymentStatus), "当前订单状态不允许支付");
        // 获取分布式交易事务id
        String transId = paymentService.transId();
        // 构造支付订单所需业务参数
        PaymentOrderCreateDTO paymentOrderCreate = buildPaymentOrderCreateDTO(productOrder);
        String paymentOrderNo = paymentService.createOrder(transId, paymentOrderCreate);
        // 商品订单绑定支付订单编号
        // 先数据库绑定，修改订单支付状态：进行中
        productOrderDAO.updateOrderPaymentInfo(orderNo, transId, paymentOrderNo, MallOrderPaymentStatusEnum.RUNNING.getStatus());
        // 刷新订单缓存
        doCacheProductOrder(orderNo);
        return paymentOrderNo;
    }

    /**
     * 根据商品订单数据生成交易订单所需请求参数对象
     *
     * @param productOrder
     * @return
     */
    private PaymentOrderCreateDTO buildPaymentOrderCreateDTO(MallUserProductOrderResponseVO productOrder) {
        MallProductOrderResponseVO order = productOrder.getOrder();
        MallSKUResponseVO sku = productOrder.getSku();
        MallShopBaseVO shop = productOrder.getShop();
        MallSPUBaseVO product = productOrder.getProduct();
        String paymentDescription = "在%s店铺下购买商品(%s)%s";
        paymentDescription = String.format(paymentDescription,
                                           shop.getName(),
                                           product.getMainTitle(),
                                           sku.getPropertyValueKey());
        PaymentOrderCreateDTO paymentOrderCreate = new PaymentOrderCreateDTO();
        paymentOrderCreate.setBusinessId(order.getOrderNo());
        paymentOrderCreate.setBusinessAction(PaymentBusinessActionEnum.MALL_PRODUCT_ORDER.getAction());
        // 应付金额（商品单价 * 购买数量 - 优惠减免费用）
        paymentOrderCreate.setAmount(order.getPaymentPrice());
        paymentOrderCreate.setBillType(PaymentTransTypeEnum.EXPENSES.getTransType());
        paymentOrderCreate.setEventType(PaymentTransEventEnum.SHOPPING.getTransEvent());
        paymentOrderCreate.setDescription(paymentDescription);
        paymentOrderCreate.setSourceAccount(order.getUserId());
        // TODO 暂时采用直接支付到店铺管理账户，续后有时间可以优化迭代支付到电商总账号（但是需要一套分账系统）
        paymentOrderCreate.setTargetAccount(shop.getCreateBy());
        return paymentOrderCreate;
    }

    public MallUserProductOrderResponseVO getUserOrder( String userId, String orderNo) {
        // 走缓存查询订单信息
        Assert.notNull(orderNo, "订单不存在");
        Assert.notNull(userId, "订单不存在");
        MallProductOrderResponseVO order = detail(orderNo);
        Assert.notNull(order, "订单不存在");
        Assert.isTrue(order.getUserId().equals(userId), "订单不存在");
        // 获取商品详情，RPC请求商品服务获取
        Long productId = order.getSpuId();
        Long skuId = order.getSkuId();
        MallSPUDetailVO product = productService.productInfo(productId);
        Assert.notNull(product, "订单商品不存在/已下架");
        // 商品基础信息
        MallSPUBaseVO productBase = new MallSPUBaseVO();
        BeanUtils.copyProperties(product, productBase);
        // 获取下单sku
        MallSKUResponseVO skuInfo = product.getSkuList().stream()
                .filter(sku -> ObjectUtils.equals(sku.getId(), skuId))
                .toList()
                .get(0);
        Assert.notNull(skuInfo, "订单中的商品款式不存在/已下架");
        return MallUserProductOrderResponseVO.builder()
                .order(order)
                .shop(product.getShop())
                .product(productBase)
                .sku(skuInfo)
                .build();
    }

    /**
     * 查询订单详情
     *
     * @return
     */
    public MallProductOrderResponseVO detail(String orderNo) {

        String cacheKey = orderCacheKey(orderNo);
        String cache = redisService.get(cacheKey);
        if (StringUtils.isNotBlank(cache)) {
            if (WebConstant.CACHE_NONE.equals(cache)) {
                return null;
            }
            return JsonUtil.fromJson(cache, MallProductOrderResponseVO.class);
        }
        return doCacheProductOrder(orderNo);
    }

    /**
     * 处理支付超时订单
     *
     * @param orderNo
     * @return
     */
    @Transactional
    public void doHandlePaymentTimeoutOrder(String orderNo, Long productId) {

        MallProductOrderResponseVO order = detail(orderNo);
        if (order == null) {
            return;
        }
        boolean isPaymentSuccess = MallOrderPaymentStatusEnum.SUCCESS.getStatus().equals(order.getPaymentStatus());
        if (!isPaymentSuccess) {
            doRollbackTimeoutOrder(orderNo, productId, order);
        }
    }

    public void doRollbackTimeoutOrder(String orderNo, Long productId, MallProductOrderResponseVO order) {
        // 1. 订单状态处理为超时未支付
        updateOrderPaymentStatus(orderNo, MallOrderPaymentStatusEnum.TIMEOUT);
        // 3. 库存rollback RPC调用
        try {
            mallProductStockService.rollback(productId, order.getSkuId(), order.getProductCount());
        } catch (Exception e) {
            // 回滚缓存
            doDelProductOrderCache(orderNo);
            throw e;
        }
    }

    /**
     * 更新订单状态方法
     *
     * @param orderNo
     * @param status
     */
    public void updateOrderPaymentStatus(String orderNo, MallOrderPaymentStatusEnum status) {
        // 1. 订单状态处理为超时未支付
        productOrderDAO.updateOrderPaymentStatus(orderNo, status.getStatus());
        // 2. 刷新订单缓存状态
        doCacheProductOrder(orderNo);
        // 3. 更新用户订单列表缓存 TODO
    }

    /**
     * 同时更新订单支付、物流状态
     *
     * @param orderNo
     * @param paymentStatusEnum
     * @param logisticsStatusEnum
     */
    public void updateOrderPaymentAndLogisticsStatus(String orderNo,
                                                     MallOrderPaymentStatusEnum paymentStatusEnum,
                                                     MallOrderLogisticsStatusEnum logisticsStatusEnum) {
        // 1. 订单状态处理为超时未支付
        productOrderDAO.updateOrderPaymentAndLogisticsStatusStatus(
                orderNo, paymentStatusEnum.getStatus(), logisticsStatusEnum.getStatus());
        // 2. 刷新订单缓存状态
        doCacheProductOrder(orderNo);
        // 3. 更新用户订单列表缓存 TODO
    }

    /**
     * 处理支付回调结果
     *
     * @param callBackRequestBody
     */
    @Override
    public boolean doCallback(PaymentResultDTO callBackRequestBody) {

        Integer paymentCode = callBackRequestBody.getCode();
        CallBackRequestBodyDTO paymentData = callBackRequestBody.getData();
        String tranceId = paymentData.getTranceId();
        // 幂等性处理
        boolean isHandle = this.isHandleTranceId(tranceId);
        if (isHandle) {
            return true;
        }
        try {
            if (ObjectUtils.equals(paymentCode, PaymentResultCodeEnum.OK.getCode())) {
                // 支付成功的
                this.doHandlePaymentSuccess(paymentData);
            } else {
                // 处理支付失败
                this.doHandlePaymentError(paymentData);
            }
        } catch (Exception e) {
            // 支付结果处理异常
            // 回滚交易数据，根据分布式事务id
            try {
                paymentService.rollBack(tranceId);
            } catch (Exception e1) {
                // 分布式交易事务回滚异常，需求走队列重试
                // 可以参考支付callback策略、也可以参考订单最终一致性队列保障策略
            }

        }
        return true;
    }


    /**
     * 处理支付成功
     *
     * @param data
     */
    private void doHandlePaymentSuccess(CallBackRequestBodyDTO data) {
        updateOrderPaymentAndLogisticsStatus(data.getBusinessId(),
                                             MallOrderPaymentStatusEnum.SUCCESS,
                                             MallOrderLogisticsStatusEnum.WAIT);
    }

    /**
     * 处理支付成功
     *
     * @param data
     */
    private void doHandlePaymentError(CallBackRequestBodyDTO data) {
        updateOrderPaymentStatus(data.getBusinessId(), MallOrderPaymentStatusEnum.ERROR);
        // 支付失败不回滚库存量，库存回滚统一由延迟队列（10分钟后为成功支付）
    }

    /**
     * 是否处理过当前回调数据
     *
     * @param tranceId
     * @return
     */
    private boolean isHandleTranceId(String tranceId) {

        // redis原子特性

        return false;
    }

    private MallProductOrderEntity convertOrderEntity(String orderNo,
                                                      PreCreateProductOrderReqVO preCreateProductOrderReq,
                                                      MallSKUResponseVO sku,
                                                      long timeoutTime) {
        String userId = preCreateProductOrderReq.getUserId();
        int productCount = preCreateProductOrderReq.getProductCount();
        BigDecimal paymentPrice = sku.getPrice().multiply(new BigDecimal(productCount));
        // 优惠券id
        Long couponId = preCreateProductOrderReq.getCouponId();
        BigDecimal couponPrice = new BigDecimal(0);
        if (couponId != null) {
            // 需要校验优惠券的有效性
            // TODO  优惠券暂未支持
            boolean validateCouponRes = true;
            if (validateCouponRes) {
                // 根据优惠券玩法（慢XXX减XXX / 全场8折）计算本地需要减免价格
                // couponPrice
            }
        }
        // 减去优惠券优惠价格
        BigDecimal payablePrice = paymentPrice.subtract(couponPrice);
        MallProductOrderEntity productOrder = new MallProductOrderEntity();
        productOrder.setOrderNo(orderNo);
        productOrder.setUserId(userId);
        productOrder.setSpuId(preCreateProductOrderReq.getSpuId());
        productOrder.setSkuId(preCreateProductOrderReq.getSkuId());
        productOrder.setProductCount(preCreateProductOrderReq.getProductCount());
        productOrder.setPaymentType(preCreateProductOrderReq.getPaymentType());
        productOrder.setCouponId(couponId);
        productOrder.setCouponPrice(couponPrice);
        productOrder.setPaymentTimeout(new Date(timeoutTime));
        // 单价
        productOrder.setPrice(sku.getPrice());
        // 应付
        productOrder.setPaymentPrice(paymentPrice);
        // 实付
        productOrder.setPayablePrice(payablePrice);
        productOrder.setPaymentStatus(MallOrderPaymentStatusEnum.WAIT.getStatus());
        productOrder.setLogisticsStatus(MallOrderLogisticsStatusEnum.NONE.getStatus());

        Date now = new Date();
        productOrder.setCreateDate(now);
        productOrder.setCreateBy(userId);
        return productOrder;
    }

    /**
     *
     * @param mallProductOrderEntity
     * @return
     */
    private MallProductOrderResponseVO convertVOByOrderEntity(MallProductOrderEntity mallProductOrderEntity) {

        MallProductOrderResponseVO vo = new MallProductOrderResponseVO();
        BeanUtils.copyProperties(mallProductOrderEntity, vo);
        if (mallProductOrderEntity.getPaymentDate() != null) {
            vo.setPaymentTime(mallProductOrderEntity.getPaymentDate().getTime());
        }
        if (mallProductOrderEntity.getPaymentTimeout() != null) {
            vo.setPaymentTimeoutTime(mallProductOrderEntity.getPaymentTimeout().getTime());
        }
        return vo;
    }

}
